﻿using Quartz;
using System;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace ZYing.QPanel
{
    public static class JobHelper
    {
        private static void OnStatusFired(IJobExecutionContext context, string status)
        {
            var time = DateTimeOffset.UtcNow;
            if (context.Scheduler.Context.TryGetExecutionHistoryStore(out var store))
            {
                store.PushStatus(context.JobDetail.Key, context.FireInstanceId, time, status);
            }
            if (StatusFired == null) return;
            var e = new StatusFiredEventArgs(context, time, status);
            StatusFired.Invoke(context.JobInstance, e);
        }

        public static event EventHandler<StatusFiredEventArgs> StatusFired;
        public static void FireStatus(IJobExecutionContext context, string status)
        {
            OnStatusFired(context, status);
        }

        private static Regex TriggerExpressRegex = new Regex("^\\+(?<num>\\d+)(?<unit>[smhd]?)$", RegexOptions.Compiled);
        public static ITrigger CreateTrigger(string name, string group, string express, Action<TriggerBuilder> builder = null)
        {
            TriggerBuilder triggerBuilder = TriggerBuilder.Create().WithIdentity(name, group);

            if (express.StartsWith("+"))
            {
                var m = TriggerExpressRegex.Match(express);
                if (!m.Success) throw new Exception($"触发器表达式不正确:{express}");
                var num = Convert.ToInt32(m.Groups["num"].Value);
                var unit = "s";
                if (m.Groups["unit"].Success) unit = m.Groups["unit"].Value;
                var intervale = TimeSpan.MaxValue;
                switch (unit)
                {
                    case "s": intervale = TimeSpan.FromSeconds(num); break;
                    case "m": intervale = TimeSpan.FromMinutes(num); break;
                    case "h": intervale = TimeSpan.FromHours(num); break;
                    case "d": intervale = TimeSpan.FromDays(num); break;
                    case "w": intervale = TimeSpan.FromDays(7 * num); break;
                    default: throw new Exception($"触发器表达式不正确:{express} , 不支持的单位:{unit}");
                }
                triggerBuilder.WithSimpleSchedule(s => s.WithInterval(intervale).RepeatForever());
            }
            else
            {
                triggerBuilder.WithCronSchedule(express);
            }
            triggerBuilder.WithDescription(express);
            if (builder != null) builder.Invoke(triggerBuilder);
            return triggerBuilder.Build();
        }

        public static async Task RefireDelay(IJobExecutionContext context, TimeSpan delay)
        {
            var trigger = TriggerBuilder
                .Create()
                .StartAt(DateTime.Now + delay)
                .WithSimpleSchedule()
                .ForJob(context.JobDetail)
                .Build();

            await context.Scheduler.ScheduleJob(trigger);
        }
    }
}
